define(function (require, exports, module) {
	
	 var CFindTool_DocViewEventHandler = require('./FindToolDocViewEventHandler');
	
	FXREADER.SearchDirection = 
	{
		Up: 0,
		Down: 1
	};
	
	FXREADER.SearchResult = function () {
        this.startCharIndex = -1;
        this.relateText = "";
        this.rects = [];          //存储搜索结构的矩形区域;
    };
    
    FXREADER.SearchingContext = function(contentToSearch,searchDirection, curPageIndex,startCharIndex)
    {
    	this.content = 	contentToSearch;
    	this.direction = searchDirection;
    	this.startPageIndex = curPageIndex;
    	this.startCharIndex = startCharIndex;
    	this.curPageIndex = curPageIndex;
    	this.curCharIndex = startCharIndex;
    };
 
    
    FXREADER.PageSearchResult = function () {
        this.pageIndex = -1;
        this.totalCharCnt = -1;
        this.curResultIndex = -1;
        this.resultList = [];
        this.isSearched = false;
        this.isHasResult = false;
        this.ClearResult = function () {
            this.pageIndex = -1;
            this.totalCharCnt = -1;
            this.curResultIndex = -1;
            this.resultList = [];
            this.isSearched = false;
            this.isHasResult = false;
        };
        this.IsLastResult = function (nCurSelIndex) {
            return nCurSelIndex == (this.resultList.length - 1);
        };
        this.IsFirstResult = function (nCurSelIndex) {
            return nCurSelIndex == 0;
        };
        this.GetNextCharIndex = function (nCurSelIndex) {
            return this.resultList[nCurSelIndex + 1].startCharIndex;
        };
        this.GetPrevCharIndex = function (nCurSelIndex) {
            return this.resultList[nCurSelIndex - 1].startCharIndex;
        };
        this.GetLastCharIndex = function () {
            var iCnt = this.resultList.length - 1;
            if (iCnt < 0)
                iCnt = 0;
            if (this.resultList[iCnt] == null)
                return 0;
            return this.resultList[iCnt].startCharIndex;
        };
    };
    
    FXREADER.SCH_CONTEXT = function() {
 	   	this.csFindWhat = "";
        this.RectArray = [];      //[Results of rect]	
        this.nSearchPos = -1;     //[the starting point to search(in text objects)]
        this.nResultCharStartPos = -1;     //[the starting point of the result in chars]
        this.nResultItemStartPos = -1;   //[the starting point of the result in items]
        this.nResultItemEndPos = -1;     //[the starting point of the result in items]
        this.bMatchCase = false;     //[Match case]
        this.bMatchWholeWord = false;//[whole word matching]
        this.bCurResult = false;     //result
    };
    
    FXREADER.FINDRESULT = function()
    {
  	  	this.nStartIndex = -1;
        this.nEndIndex = -1;
        this.nResultCharStartPos = -1;  
    };
    
    FXREADER.SEARCH_PARAM = function()
    {
    	this.startCharIndex = -1;
    	this.endCharIndex = -1;
    };
    
    /**
     * 搜索参数;
     * @param [iPageIndex] 页面索引;
     * @param [iCharIndex] 相对于页面的字符索引;
     */
     FXREADER.CSearchParam = function (pageIndex, charIndex) {
         this.pageIndex = pageIndex;
         this.charIndex = charIndex;
     };

	
	FXREADER.CFindToolPlugin = function (pReaderApp) {
		var _pReaderApp = pReaderApp,
			_isSearching = false,
			_isCaseSensitive = false,
			_isMatchWholeWord = false,
			_Language = _pReaderApp.GetLanguage(),
			_contentToSearch = "",
			_tempContentToSearch = "",
			//_firstSearchedCharIndex = -1,
			//_firstSearchedPageIndex = -1,
			_curSearchedPageIndex = -1,                //上一次搜索结果所处页面;
            _curSearchedCharIndex = -1,                  //上一次搜索结果的字符索引;
            _curSelResultIndex = -1,                     //上一次搜索结果相对于页面搜索结果的索引（一个页面包含多个搜索结果 SearchResult）;
			_pageFindCacheResults = [],
			_textManager = _pReaderApp.GetTextManager(),
			_SearchDivID = null, 
            _SearchLoadingTextId = _SearchDivID + "_LoadingText",  //搜索层文本ID
            _SearchingText = "Searching",                                          //搜索层文本;
            _HighlightRects = null,  //当前需要高亮的矩形区域;
            _PageHighlightCreatedList = {},  // 存储已经创建highlight div的页面索引,格式为 :   页面索引：true/fase;
            _isSearchingBlocked = false, //当前搜索是否block住（正在从服务端获取文本)
            _searchContext = null,
            _cancelSearch = false,
		 	_self = this;
		
		function IsNewSearch(newContentToSearch) {
            return !(_contentToSearch == newContentToSearch);
        }
		
		function ClearSearchResult() {
			_contentToSearch = '';
	        _self.ResetHighLightText(true);
			_curSearchedCharIndex = -1;
			_curSearchedPageIndex = -1;
			_curSelResultIndex = -1;
			//_firstSearchedPageIndex = -1;
	       // _firstSearchedCharIndex = -1;
	        var iPageCnt = _pReaderApp.GetMainView().GetDocView().GetPageCount();
	        for (var i = 0; i < iPageCnt; i++) {
	        	_pageFindCacheResults[i].ClearResult();
	        }
	    }
		
		function GetHighlightDivID(pPageView) {
            return pPageView.GetPageContainerID() + "_HighLights";
        }
		
		this.SetSearchParam = function (bCaseSensitive, bMarchWholeWord) {
            if (_isSearching == 1)
                return;
            if (_isCaseSensitive != bCaseSensitive || _isMatchWholeWord != bMarchWholeWord)
            	ClearSearchResult();
            _isCaseSensitive = bCaseSensitive;
            _isMatchWholeWord = bMarchWholeWord;
        };
		
		this.ShowSearchingDiv = function (bShow) {
			var jqobj = $("#" + _SearchDivID);
			bShow ? jqobj.show() : jqobj.hide();
			if(FXREADER.Environment.mobile || FXREADER.Environment.iOS)
			{
				var jqWapSearchBar = $("#fwr_search_wap_bar");
				bShow ? jqWapSearchBar.hide() : jqWapSearchBar.show();
			}
	    };
		
	    this.UpdateSearchLoadingText = function (iStep) {
            var text = _SearchingText;
            for (var i = 0; i < iStep; i++)
                text = text + ".";
            $("#" + _SearchLoadingTextId).text(text);
        };
        
        this.SetHightlightRects = function (rects) {
            _HighlightRects = [];
            _HighlightRects = rects.concat();
        };

        this.ResetHighLightText = function (bClearRects) {
			if(bClearRects == true)
				 _HighlightRects = [];
            var pPageView = _pReaderApp.GetMainView().GetDocView().GetPageView(_curSearchedPageIndex);
            if (pPageView != null) {
                var highLightDivID = GetHighlightDivID(pPageView);
                var jqHighlightDiv = $("#" + highLightDivID);
                if (jqHighlightDiv != null) {
                    jqHighlightDiv.empty();
                }
            }
        };
        
        this.HilightSearchedText = function (iPageIndex, highlightRects) {
            var pDocView = _pReaderApp.GetMainView().GetDocView();
            if (iPageIndex < 0 || iPageIndex >= pDocView.GetPageCount())
                return false;
            var pPageView = pDocView.GetPageView(iPageIndex);
            if (!pPageView.IsContentCreated())
                pDocView.GotoPage(iPageIndex, 0, 0);
            var offset = _self.GetHighlightOffset2Scroll(pPageView, highlightRects);
            if (offset.x != -1 && offset.y != -1) {
                pDocView.GotoPage(iPageIndex, offset.x, offset.y);
            }
            _self.HighLightRects(pPageView, highlightRects);
        };
        
        this.HighLightRects = function (pPageView, highlightRects) {
            if (pPageView == null || !pPageView.IsContentCreated() || highlightRects == null)
                return false;
            var highLightDivID = GetHighlightDivID(pPageView);
            if (_PageHighlightCreatedList[pPageView.GetPageIndex()] == null) {
                var highLightDivHtml = "<div id='" + highLightDivID + "' style='z-index:7;'></div>";
                var jqPageView = $("#" + pPageView.GetPageContainerID());
                jqPageView.append(highLightDivHtml);
                _PageHighlightCreatedList[pPageView.GetPageIndex()] = true;
            }
            var jqHighlightDiv = $("#" + highLightDivID);
            jqHighlightDiv.empty(); //清空原有的div内容;

            var highLightDivContent = "";
            for (var i = 0; i < highlightRects.length; i++) {
                var rect = highlightRects[i];
                FXREADER.RectUtils.Normalize(rect);
                rect = pPageView.PDF2Doc(rect, true);
                highLightDivContent += "<div id='" + "highlight_" + pPageView.GetPageIndex() + "_" + i + "'class='fwr_search_text_highlight' style='left:" +
                             rect.left + "px;top:" + rect.top + "px;width:" + FXREADER.RectUtils.Width(rect) + "px;height:" + FXREADER.RectUtils.Height(rect) + "px' ></div>";
            }
            jqHighlightDiv.append(highLightDivContent);
        };
        
      //根据页面和需要高亮的区域，获取滚动条需要移动的位置; 返回{x:-1,y:-1}代表可见或获取失败
        this.GetHighlightOffset2Scroll = function (pPageView, highlightRects) {
            if (highlightRects.length <= 0)
                return { x: -1, y: -1 };
            var first_rect = highlightRects[0];
            FXREADER.RectUtils.Normalize(first_rect);
            var union_rect = new FXREADER.CPDF_Rect(first_rect.left, first_rect.top, first_rect.right, first_rect.bottom);
            for (var i = 1; i < highlightRects.length; i++) {
                var tmp_rect = highlightRects[i];
                FXREADER.RectUtils.Normalize(tmp_rect);
                FXREADER.RectUtils.Union(union_rect,tmp_rect);
            }
            var pDocView = _pReaderApp.GetMainView().GetDocView();
            var jqDocView = $("#" + pDocView.GetDocViewContainerID());
            var pagesContainerHeight = jqDocView.height(), pagesContainerWidth = jqDocView.width(),
                    pagesContainerOffset = jqDocView.offset();
            var jqPageView = $("#" + pPageView.GetPageContainerID());
            if (pPageView.GetDocView().GetViewMode() == FXREADER.PDFView.RD_BRMODE_CONTINUOUS_FACING) { //双页；
                //暂时不处理；
            }
            else if (pPageView.GetDocView().GetViewMode() == FXREADER.PDFView.RD_BRMODE_CONTINUOUS) { //单页；
                var pageOffset = jqPageView.offset();
                var docrect = pPageView.PDF2Doc(union_rect, true);
                var center_y = pagesContainerHeight / 2;
                var center_x = pagesContainerWidth / 2;
                var bVisable = ((pageOffset.top + docrect.top >= pagesContainerOffset.top) && (pageOffset.top + docrect.top <= pagesContainerOffset.top + pagesContainerHeight))
                                                || ((pageOffset.top + docrect.top <= pagesContainerOffset.top) && (pageOffset.top + docrect.top + FXREADER.RectUtils.Height(docrect) >= pagesContainerOffset.top));
                bVisable &= ((pageOffset.left + docrect.left >= pagesContainerOffset.left) && (pageOffset.left + docrect.left <= pagesContainerOffset.left + pagesContainerWidth))
                                                || ((pageOffset.left + docrect.left <= pagesContainerOffset.left) && (pageOffset.left + docrect.left + FXREADER.RectUtils.Width(docrect) >= pagesContainerOffset.left));
                if (bVisable == 1)
                    return { x: -1, y: -1 };
                var rect_top_pos_y = FXREADER.RectUtils.Height(docrect) / 2;
                page_top_pos_y = rect_top_pos_y + docrect.top;
                page_top_pos_y = center_y - page_top_pos_y;
                page_top_pos_y = -page_top_pos_y;
                var rect_left_pos_x = FXREADER.RectUtils.Width(docrect) / 2;
                var page_left_pos_x = rect_left_pos_x + docrect.left;
                page_left_pos_x = center_x - page_left_pos_x;
                page_left_pos_x = -page_left_pos_x;

                return { x: page_left_pos_x, y: page_top_pos_y };
            }
        };
        
        this.CancelSearching = function()
        {
        	 if(_isSearching == false)
				 return;
        	 this._searchContext = null;
        	 _isSearchingBlocked = false;
        	 _cancelSearch = true;
        };
        
        this.ContinueToSearch = function()
        {
        	if(_searchContext != null)
        	{
        		_isSearchingBlocked = false;
        		var bFound = false;
        		var totalPageCount = _pReaderApp.GetMainView().GetDocView().GetPageCount();
        		 _tempContentToSearch = _searchContext.content;
        		if (_searchContext.direction == FXREADER.SearchDirection.Down)
                {
        			if(_searchContext.curPageIndex >= _searchContext.startPageIndex)
        			{
        				bFound = _self.SearchInRange(_searchContext.curPageIndex,totalPageCount-1, _searchContext.startCharIndex, _searchContext.direction);
                        if (!bFound)
                       	 bFound = this.SearchInRange(0, _searchContext.startPageIndex, _searchContext.startCharIndex, _searchContext.direction); //返回文档头部开始搜
        			}
        			else
        			{
                       	bFound = this.SearchInRange(_searchContext.curPageIndex, _searchContext.startPageIndex, _searchContext.startCharIndex, _searchContext.direction); //返回文档头部开始搜
        			}
                }
                else
                {
                	if(_searchContext.curPageIndex <= _searchContext.startPageIndex)
                	{
                		bFound = _self.SearchInRange(0, _searchContext.curPageIndex, _searchContext.startPageIndex,_searchContext.direction);
                        if (!bFound)
                       	 bFound = _self.SearchInRange(_searchContext.startPageIndex+1, totalPageCount-1, _searchContext.startPageIndex,_searchContext.direction);
                	}
                	else
                	{
                		bFound = _self.SearchInRange(_searchContext.startPageIndex+1, _searchContext.curPageIndex, _searchContext.startPageIndex,_searchContext.direction);
                	}
                }
        		if(_cancelSearch)
	   			 {
	   				_cancelSearch = false;
	   				_self.ShowSearchingDiv(false);
	   				return false;
	   			 }
        		if(!_isSearchingBlocked)
    			{
    				 _searchContext = null;
    				 _self.ShowSearchingDiv(false);
    				 if(!bFound)
    				 {
    					 FXREADER.Alert("", _Language.Search.NoFound,null,null,null,true);
    				 }
    				 return bFound;	 
    			}
        	}
        };
	    
		this.SearchText = function (contentToSearch, searchDirection, curPageIndex,startCharIndex)
		{
			 if(_isSearching == true)
				 return;
			_searchContext = new FXREADER.SearchingContext(contentToSearch, searchDirection, curPageIndex,startCharIndex);
			_cancelSearch = false; 
			var totalPageCount = _pReaderApp.GetMainView().GetDocView().GetPageCount();
			 if(contentToSearch=='' || contentToSearch==null || curPageIndex<0)
                 return;
			 _tempContentToSearch = contentToSearch;
			 _self.ShowSearchingDiv(true);  //显示搜索层
			 _isSearchingBlocked = false;
			 var bFound = false;
			 var isNewSearch = IsNewSearch(contentToSearch);
			 if(isNewSearch)
			 {
				 ClearSearchResult();
			 }
			 if (searchDirection == FXREADER.SearchDirection.Down)
             {
				 bFound = _self.SearchInRange(curPageIndex,totalPageCount-1, startCharIndex, searchDirection);
                 if (!bFound)
                	 bFound = this.SearchInRange(0, curPageIndex, startCharIndex,searchDirection); //返回文档头部开始搜
             }
             else
             {
            	 bFound = _self.SearchInRange(0, curPageIndex, startCharIndex,searchDirection);
                 if (!bFound)
                	 bFound = _self.SearchInRange(curPageIndex+1, totalPageCount-1, startCharIndex, searchDirection);
             }
			 if(_cancelSearch)
			 {
				_cancelSearch = false;
				_self.ShowSearchingDiv(false);
				return false;
			 }
			 if(!_isSearchingBlocked)
			 {
				 _searchContext = null;
				 _self.ShowSearchingDiv(false);
				 if(!bFound)
				 {
					 FXREADER.Alert("", _Language.Search.NoFound,null,null,null,true);
				 }
				 return bFound;	 
			 }
			
			 /*if(isNewSearch)
			 {
				 ClearSearchResult();
				 if(searchDirection == FXREADER.SearchDirection.Down)
				 {
					 bFound = _self.SearchInRange(curPageIndex,totalPageCount-1,-1,searchDirection);
					 if(!bFound)
						 bFound = _self.SearchInRange(0,iCurPageIndex-1,-1,searchDirection); 
				 }
				 else
				 {
					 bFound = _self.SearchInRange(0,iCurPageIndex-1,-1,searchDirection);
					 if(!bFound)
						 bFound = _self.SearchInRange(curPageIndex,totalPageCount-1,-1,searchDirection);
				 }
			 }
			 else
			 {
				 if(_firstSearchedPageIndex < curPageIndex)
				 {
					if (searchDirection == FXREADER.SearchDirection.Down)
					{
						bFound = _self.SearchInRange(curPageIndex,totalPageCount-1,-1,searchDirection);
						if (!bFound)
							bFound = this.SearchInRange(0,_firstSearchedPageIndex-1,-1,searchDirection);
					}
					else
					{
						bFound = this.SearchInRange(_firstSearchedPageIndex+1,curPageIndex,-1,searchDirection);
					}
				 }
				 else if(_firstSearchedPageIndex == curPageIndex)
				 {
					bFound = _self.SearchInRange(curPageIndex,curPageIndex,_firstSearchedCharIndex+1,searchDirection);
				 }
				 else
				 {
					if (searchDirection == FXREADER.SearchDirection.Down)
					{
						bFound = _self.SearchInRange(curPageIndex,_firstSearchedPageIndex,-1,searchDirection);
					}
					else
					{
						bFound = _self.SearchInRange(0,curPageIndex,-1,searchDirection); 
						if (!bFound)
							bFound = _self.SearchInRange(_firstSearchedPageIndex+1,totalPageCount-1,-1,searchDirection); 
					}
				 }
			 }*/
			 
		};
		
		this.SearchInRange = function(startPageIndex, endPageIndex, startCharIndex,searchDirection)
		{
			 var bFound = false;
			 var i = 0;
			 if(searchDirection == FXREADER.SearchDirection.Down)
			 {
				for (i=startPageIndex; i<=endPageIndex; i++)
				{
					if(!_cancelSearch)
					{
						bFound = _self.SearchInPage(i,startCharIndex,searchDirection);
						if(bFound)
							return true;
					}
					else return false;
				}
			 }
			 else
			 {
				for (i=endPageIndex; i>=startPageIndex; i--)
				{
					if(!_cancelSearch)
					{
						bFound = _self.SearchInPage(i,startCharIndex,searchDirection);
						if(bFound)
							return true;
					}
					else return false;
				}
			 }
			 return false;
		};
		
		this.SearchInPage = function(pageIndex,startCharIndex,searchDirection)
		{
			//var bFound = false;
			var pageResult = _pageFindCacheResults[pageIndex];
			if (pageResult==null || pageResult.isSearched==false)
            {
				var textPage = _self.CreateATextPage(pageIndex);
				if(textPage == null)
				{
					if(_isSearchingBlocked)
					{
						_searchContext.curPageIndex = pageIndex;
						_searchContext.curCharIndex = startCharIndex;
						setTimeout(function(){_self.ContinueToSearch();},100);
					}
					return true;
				}
				
				var pageResult = new FXREADER.PageSearchResult();
				pageResult.pageIndex = pageIndex;
				pageResult.totalCharCnt = textPage.GetStrSize();
				var schContext =  _self.CreateSearchContext(); //FXREADER.FINDRESULT
				var bFindResult = false;
				do
				{
					var result = new FXREADER.FINDRESULT();
					var bIsFind = _self.FindNext(schContext, result,textPage);
					if (bIsFind)
					{
						var bInPage = false;
						if (result.nStartIndex >= 0)
						{
							bInPage = true;
						}
						if (bInPage)
						{
							bFindResult = true;
							var find_result = new FXREADER.SearchResult();
							find_result.startCharIndex = result.nResultCharStartPos;
							find_result.rects = schContext.RectArray;
							pageResult.resultList.push(find_result);
						}
					}
					else
					{
						break;
					}
				}while (true);
				if(!bFindResult)
					return false;
				pageResult.isSearched = true;
				pageResult.isHasResult = true;
				_pageFindCacheResults[pageIndex] = pageResult;
			}
			
			var findResult = _self.SearchInPageCache(pageResult,startCharIndex,searchDirection);
			if(findResult != null)
			{
				_self.ResetHighLightText(true);
				var result = findResult.ret;
				var bSameResult = (_curSearchedCharIndex==result.startCharIndex &&
						_curSelResultIndex==findResult.index && _curSearchedPageIndex==pageIndex);
				_curSearchedPageIndex = pageIndex;
		        _self.SetHightlightRects(result.rects);
				if(!bSameResult)
					_self.HilightSearchedText(_curSearchedPageIndex, _HighlightRects);
				else
					setTimeout(function(){_self.HilightSearchedText(_curSearchedPageIndex, _HighlightRects);},50);
				_curSearchedCharIndex = result.startCharIndex;
				_contentToSearch = _tempContentToSearch;
				_tempContentToSearch = "";
				_curSelResultIndex = findResult.index;
			}
			return findResult != null;
		};
		
		
		this.SearchInPageCache = function(pageResult,startCharIndex,searchDirection) {
            if (pageResult==null || pageResult.isSearched==false)
            {
				return null;
			}
            if (searchDirection == FXREADER.SearchDirection.Down) {
                for (var j=0; j<pageResult.resultList.length; j++) {
                    var result = pageResult.resultList[j];
                    if(startCharIndex == -1)
                    {
                    	return {ret:result,index:j};
                    }
                    if (result.startCharIndex >= startCharIndex) {
                         return {ret:result,index:j};
                    }
                }
            }
            else {
                for (var j=pageResult.resultList.length-1; j>=0; j--) {
                    var result = pageResult.resultList[j];
                    if(startCharIndex == -1)
                    {
                    	return {ret:result,index:j};
                    }
                    if (result.startCharIndex <= startCharIndex) {
                       return {ret:result,index:j};
                    }
                }
            }

            return null;
        };
        
        this.CreateATextPage = function(pageIndex)
        {
        	var textPage = _textManager.GetTextPage(pageIndex,false);
        	if(textPage.blocking === true)
        	{
        		_isSearchingBlocked = true;
        		return null;
        	}
        	return textPage;
        };
        
        this.CreateSearchContext = function()
    	{
    		var  pSCHContext = new FXREADER.SCH_CONTEXT();
    		pSCHContext.bMatchCase = _isCaseSensitive;
    		pSCHContext.bMatchWholeWord = _isMatchWholeWord;
    		pSCHContext.RectArray = [];
    		pSCHContext.csFindWhat = _tempContentToSearch;
    		pSCHContext.nSearchPos = 0;	
    		pSCHContext.nResultCharStartPos     =-1;
    		pSCHContext.nResultItemStartPos = -1;
    		pSCHContext.nResultItemEndPos = -1;
    		pSCHContext.nSearchPos = 0;
    		pSCHContext.bCurResult  = false;
    		pSCHContext.nSearchPos = 0;
    		return pSCHContext;
    	};
    	
    	this.FindNext = function(pContext,result,pTextPage)
    	{
    		pContext.RectArray = []; //[Clear data]
    		pContext.nResultItemEndPos = -1;
    		pContext.nResultItemStartPos = -1;

    		if (pContext.nResultCharStartPos != -1)
    			pContext.nSearchPos = pContext.nResultCharStartPos + 1;//[Next Search pos]
    		if (!this.FPDF_FindPage(pContext,pTextPage))
    		{
    			pContext.bCurResult = false;
    			return false;
    		}	
    		result.nStartIndex = pContext.nResultItemStartPos;
    		result.nEndIndex = pContext.nResultItemEndPos;
    		result.nResultCharStartPos = pContext.nResultCharStartPos;
    		pContext.bCurResult = true;
    		return true;	
    	};
    	
    	this.FPDF_FindPage = function(SCHContext,pTextPage)
    	{
    		SCHContext.nResultCharStartPos = -1;
    		SCHContext.nResultItemStartPos = -1;
    		SCHContext.nResultItemEndPos = -1;
    		var csPageText = pTextPage.GetPageAllText();	
    		if(csPageText==null || csPageText.length==0){	
    			return false;
    		}
    		if(!SCHContext.bMatchCase){
    			csPageText = csPageText.toLowerCase();
    		}
    		var  csFindText = SCHContext.csFindWhat;
    		csFindText = csFindText.replace(/(^\s*)|(\s*$)/g, "");
    		if (!SCHContext.bMatchCase)
    		{
    			csFindText = csFindText.toLowerCase();
    		}
    		csFindText.replace("  ", " ");
    		if (SCHContext.bMatchWholeWord)
    		{
    			csFindText = ' ' + csFindText + ' ';
    			csPageText = ' ' + csPageText + ' ';
    		}
    		
    		var bRet = false;
    		var searchParam = new FXREADER.SEARCH_PARAM();
    		bRet = _self.NextIndex(csPageText,csFindText,SCHContext.nSearchPos,searchParam);
    		if (!bRet)
    		{
    			return false;
    		}
    		var startCharIndex = searchParam.startCharIndex,endCharIndex=searchParam.endCharIndex;
    		if (SCHContext.bMatchWholeWord)
    		{
    			endCharIndex -= 2;
    		}
    		var objStartIndex = pTextPage.GetIndexByCharIndex(startCharIndex);
    		var objEndIndex = pTextPage.GetIndexByCharIndex(endCharIndex);

    		SCHContext.nResultCharStartPos = startCharIndex;
    		SCHContext.nResultItemStartPos = objStartIndex;
    		SCHContext.nResultItemEndPos = objEndIndex;
    		if (objEndIndex==-1 || objStartIndex==-1)
    			return false;
    		var rectArray = pTextPage.GetPDFRect(objStartIndex,objEndIndex-objStartIndex+1);
    		if (rectArray.length== 0)
    			return false;
    		SCHContext.RectArray = rectArray;
    		return true;
    	};

    	this.NextIndex = function(S,T,pos,searchParam)
    	{
    		var start_Pos = searchParam.startCharIndex,end_Pos = searchParam.endCharIndex;
    		var k=pos, j=0;
    		var sLen = S.length;
    		var tLen = T.length ;
    		start_Pos = k;
    		while(k < sLen && j<tLen)
    		{
    			if (S.charAt(k) == T.charAt(j)
    					|| ((S.charAt(k)=='\r' && k<sLen-1 && S.charAt(k+1) == '\n') && T.charAt(j)==' ') 
    					|| ((S.charAt(k)=='\n' && k>0 && S.charAt(k-1) == '\r') && T.charAt(j)==' ')
    					||  ((j == 0 || j==tLen-1)&& T.charAt(j)==' ' &&  !( (S.charAt(k)>= 'a' && S.charAt(k)<='z') 
    							|| (S.charAt(k)>= 'A' && S.charAt(k)<='Z')) ))
    			{
    				if (j == 0)
    				{
    					start_Pos = k;
    				}
    				++k;
    				++j;
    			}
    			//If the same, continue backwards
    			else if( j != 0 && S.charAt(k) == '-')
    			{
    				++k;
    			}
                else if (j!=0 && (S.charAt(k)=='\r' && k<sLen-1 && S.charAt(k+1) == '\n') && !(j-1==0 && T.charAt(j-1)==' '))
    			{
    				++k;
    			}
    			else if (j!=0 && (S.charAt(k)=='\n' && k>0 && S.charAt(k-1) == '\r') && !(j-1==0 && T.charAt(j-1)==' '))
    			{
    				++k;
    			}
    			else if (S.charAt(k)==' ' && j>1  && T.charAt(j-1)==' ')
    			{
    				++k;
    			}
    			else 
    			{
    				start_Pos = start_Pos+1; 
    				k = start_Pos; 
    				j =0;
    			}
    		}
    		if (j>=tLen)
    		{
    			end_Pos=k-1;
    		}
    		else
    		{
    			return false;
    		}
    		searchParam.startCharIndex = start_Pos;
    		searchParam.endCharIndex = end_Pos;
    		return true;
    	};
    	
       
	    
	    function _SearchTextCall(searchDirection) {
            var jqTextSearch = $("#textsearch");
            if (jqTextSearch != null) {
                var txtSearch = jqTextSearch.val();
                txtSearch = txtSearch.replace(/(^\s*)|(\s*$)/g, "");
                if (txtSearch == '')
                    return;
                if (searchDirection == FXREADER.SearchDirection.Down)
                    _self.SearchTextDown(txtSearch);
                else
                    _self.SearchTextUp(txtSearch);
            }
        }
	    
	    //获取下一个搜索的位置;
        this.GetNextSearchIndex = function (txt2Search) {
        	var isNewSearch = IsNewSearch(txt2Search);
			if(isNewSearch)
			{
				 return "New";
			}
            var pageResult = _pageFindCacheResults[_curSearchedPageIndex];
            if (pageResult.IsLastResult(_curSelResultIndex)) {
                var nextPage = _curSearchedPageIndex >= _pageFindCacheResults.length - 1 ? 0 : _curSearchedPageIndex + 1;
				var nextCharIndex = 0;
                return new FXREADER.CSearchParam(nextPage, nextCharIndex);
            }
            else {
                return new FXREADER.CSearchParam(_curSearchedPageIndex, pageResult.GetNextCharIndex(_curSelResultIndex));
            }
        };
        
      //获取上一个搜索的位置;
        this.GetPrevSearchIndex = function (txt2Search) {
        	var isNewSearch = IsNewSearch(txt2Search);
			if(isNewSearch)
			{
				 return "New";
			}
            var iPageCnt = _pReaderApp.GetMainView().GetDocView().GetPageCount();
            var pageResult = _pageFindCacheResults[_curSearchedPageIndex];
            if (pageResult.IsFirstResult(_curSelResultIndex)) {
				var nextPage = 0;
                if (_curSearchedPageIndex >= 1)
                	nextPage = _curSearchedPageIndex - 1;
				else
					nextPage = iPageCnt - 1;
                return new FXREADER.CSearchParam(nextPage,-1);
            }
            else {
                return new FXREADER.CSearchParam(_curSearchedPageIndex, pageResult.GetPrevCharIndex(_curSelResultIndex));
            }
        };
	    
	    this.SearchTextDown = function (txt2Search) {
            var nextSearch = _self.GetNextSearchIndex(txt2Search);
            var iCurPageIndex = _pReaderApp.GetMainView().GetDocView().GetCurPageIndex();
            if (nextSearch == "New") {
                _self.SearchText(txt2Search, FXREADER.SearchDirection.Down, iCurPageIndex, -1);
            }
            else {
                _self.SearchText(txt2Search,FXREADER.SearchDirection.Down, nextSearch.pageIndex, nextSearch.charIndex);
            }
        };
        
        this.SearchTextUp = function (txt2Search) {
            var nextSearch = _self.GetPrevSearchIndex(txt2Search);
            var iCurPageIndex = _pReaderApp.GetMainView().GetDocView().GetCurPageIndex();
            if (nextSearch == "New") {
               _self.SearchText(txt2Search,FXREADER.SearchDirection.Up, iCurPageIndex, -1);
            }
            else {
               _self.SearchText(txt2Search,FXREADER.SearchDirection.Up, nextSearch.pageIndex, nextSearch.charIndex);
            }
        };
        
        //获取Plugin名称;
        this.GetPluginName = function () {
            return "Find Tool Plugin";
        };
        //插件被注册的时候调用;
        this.PIOnRegister = function () {
            
        };
		
		this.PIInit = function () {
			 _SearchDivID = _pReaderApp.GetMainView().GetDocView().GetDocViewContainerID() + "_SearchingDiv";  //搜索层的id;
			 _SearchLoadingTextId = _SearchDivID + "_LoadingText",
			 _self.CreateCmdAndCmdUI();
	         var iPageCnt = _pReaderApp.GetMainView().GetDocView().GetPageCount();
	         for (var i = 0; i < iPageCnt; i++) {
	        	 _pageFindCacheResults[i] = new FXREADER.PageSearchResult();
	         }
	         if(!(FXREADER.Environment.mobile || FXREADER.Environment.iOS))
			 {
	        	  $("#" + _pReaderApp.GetMainView().GetMainFrameID()).append("<div id='" + _SearchDivID + "' class='fwr_searching_div' ><img src='images/searching_loading.gif' class='fwr_searching_div_content' style='width: 16px;height: 16px;margin-left: 66px;margin-top: 5px;float: left;'></img><label class='fxsearching_divcontent' style='margin-left: 10px;margin-top: 1px;float: left;' id='" + _SearchLoadingTextId + "'>Searching...</label></div>");
			 }
	         else
	         {
	        	  $("#" + _pReaderApp.GetMainView().GetMainFrameID()).append("<div id='" + _SearchDivID + "' class='fwr_searching_div_wap' ><img src='images/wap/search_loading_wap.gif' class='fwr_searching_div_content_wap' style='width: 32px;height: 32px;margin-left: 46px;margin-top: 10px;float: left;'></img><label class='fxsearching_divcontent' style='margin-left: 10px;margin-top: 6px;float: left;' id='" + _SearchLoadingTextId + "'>Searching...</label></div>");
	         }
	         _self.ShowSearchingDiv(false);
	         var pFindToolDocViewEventHandler = new CFindTool_DocViewEventHandler(_self);
	         _pReaderApp.RegisterDocViewEventHandler(pFindToolDocViewEventHandler);
	         _pReaderApp.StepProgress();   
	    };
	    
	  //模块卸载;
        this.PIUnload = function () {
        };

        this.GetReaderApp = function () {
            return _pReaderApp;
        };
	    
	    this.CreateCmdAndCmdUI = function () {
            _pReaderApp.AddCommandUI({
                UIName: "SearchText",
                CommandName: null,
                State: false,
                CreateHtmlContentFunc: function () {
                	if(FXREADER.Environment.mobile || FXREADER.Environment.iOS)
					{
						return "<div class='fwr_search_wap_btn' id='search_wapbtn' style='float:left'><img src='images/wap/search_wap.png' width='36' height='36'></div>";
								
					}
					return "<div id='fwr_search_ui_area' class='fwr_search_ui_area fwr_toolbar_btn_margin' aria-labelledby='SearchHiddenLabel'>" +
                    			"<div id='SearchHiddenLabel' aria-hidden='true' style='cursor: text;padding-left: 3px;padding-top: 2px;color: #D7D7D7;display: hidden; position: absolute;'>Search for...</div>"+
                    			"<div id='fwr_search_box_buttom_frame' class='fwr_search_box_buttom_frame'>"+
                    				"<span class='fwr_search_split_button' title='' tabindex='0' id='FindSplitButton-Small' >" +
                    					"<a tabindex='-1' style='float: left;height:100%' title=''>" +
                    						"<span>" +
                    						 	"<span style='float:left;height:100%'>"+
                    						 		"<img alt='' id='fwr_search_icon' src='images/search.png' style=''>"+
                    						 	"</span>" +
                    						 "</span>" +	
                    					"</a>"+
                    					/*"<a tabindex='-1' style='padding: 13px 3px;width: 17px;display: inline-block;float:left;border-left-width: 0px;border-right-width: 1px;' title='Search options'>" +
                						 	"<span style='display: block;width: 5px;height: 3px;margin-left: auto;margin-right: auto;position: relative;overflow: hidden;text-align: left;z-index: 0;'>"+
                						 		"<img alt='' src='' style=''>"+
                						 	"</span>" +
                						 "</a>"+*/
                    				"</span>"+
                    				"<input id='textsearch' class='fwr_search_box' type='text' autocomplete='off' title='' maxlength='255'/>" +
                    		"</div>"+
                    		"</div>";
                },
                OnCommandStateChange: function (data) {
                },
                Init: function () {
                	if(FXREADER.Environment.mobile || FXREADER.Environment.iOS)
					{
                		var searchWapBarHtml  = "<div id='fwr_search_wap_bar' style='display: none;position: absolute;width: 100%;'>" +
						"<div class='fwr_search_wap_block'>"+
						"<input type='search' id='textsearch' style='padding:0px;width:80%; height:100%; line-height:42px; border:0; font-size:22px;float:left' >" +
						"<div id='search_wap_btn_search' class='fwr_search_wap_btn_large' style='width:20%;float:right;height:42px;line-height:42px; color:#fff; font-size:16px; background-color:#3e82e3; text-align:center;'>Search</div>" +
						"</div>" +
					"</div>";
						$("#"+_pReaderApp.GetTopPanelID()).append(searchWapBarHtml);
						$("#search_wapbtn").bind("click",function(){
								$("#fx_doc_qrcode_image").hide();
								$("#fwr_search_wap_bar").toggle();
								if($("#fwr_search_wap_bar").is(":visible"))
								{
									$("#textsearch").focus();
								}
						});
						$("#search_wap_btn_search").bind("click", function () {
			               _SearchTextCall(FXREADER.SearchDirection.Down);
			                return true;
			            });
						$("#textsearch").bind("keypress", function (d) {
	                            d.keyCode == "13" && _SearchTextCall(FXREADER.SearchDirection.Down);
	                            return true;
	                        });
						return;
					}
                    var jqTextSearch = $("#textsearch");
                    jqTextSearch.removeAttr("disabled");
                    $(function () {
                        function _UpdataBtnState() {
                            var txtSearch = jqTextSearch.val();
                            txtSearch = txtSearch.replace(/(^\s*)|(\s*$)/g, "");
                            var bEnable = !(txtSearch == "");
                            var pSearchPrevCommand = _pReaderApp.GetCommand("SearchPrev");
                            pSearchPrevCommand && pSearchPrevCommand.SetState(bEnable);
                            var pSearchNextCommand = _pReaderApp.GetCommand("SearchNext");
                            pSearchNextCommand && pSearchNextCommand.SetState(bEnable);
                        	var jqSearchIcon = $("#fwr_search_icon");
							if(bEnable)
							{	
								jqSearchIcon.attr("src","images/search_clear.png");  
								jqSearchIcon.css({cursor:"pointer"});
								$("#SearchHiddenLabel").hide();
							}
							else
							{
								jqSearchIcon.attr("src","images/search.png"); 
								jqSearchIcon.css({cursor:"default"});
								
							}
                        }
                        $("#fwr_search_icon").bind("click", function () {
                            jqTextSearch.val("");
						
							_UpdataBtnState();
		
							jqTextSearch.focus();
                            return true;
                        });
                        $("#SearchHiddenLabel").bind("click",function(){
                        	$(this).hide();
                        	jqTextSearch.focus();
                        });
                        //IE
                        if (FXREADER.Environment.ie) {
                            jqTextSearch.get(0).attachEvent("onpropertychange", function (o) {
                                _UpdataBtnState();
                            });
                            //非IE
                        } else {
                            jqTextSearch.get(0).addEventListener("input", function (o) {
                                _UpdataBtnState();
                            }, false);
                        }

                        jqTextSearch.bind("click", function () {
                            jqTextSearch.focus();
                            $("#SearchHiddenLabel").hide();
                            return true;
                        });
                        jqTextSearch.bind("keypress", function (d) {
                            d.keyCode == "13" && _SearchTextCall(FXREADER.SearchDirection.Down);
                            return true;
                        });
                        jqTextSearch.bind("blur",function(e){
                        	 var txtSearch = jqTextSearch.val();
                             txtSearch = txtSearch.replace(/(^\s*)|(\s*$)/g, "");
                             var bEnable = !(txtSearch == "");
                             if(!bEnable)
                             {
                            	var activeEle = $(document.activeElement);
                            	if(activeEle==null || activeEle.get(0).id != "textsearch")
 								{
                            		 $("#SearchHiddenLabel").show();
 								}
                            	 
                             }
                        });


                        jQuery.hotkeys.add('f3', function () {
                            _SearchTextCall(FXREADER.SearchDirection.Down);
                            return false;
                        });

                        jQuery.hotkeys.add('Shift+f3', function () {
                            _SearchTextCall(FXREADER.SearchDirection.Up);
                            return false;
                        });

                    });
                }
            });
            if(!(FXREADER.Environment.mobile || FXREADER.Environment.iOS))
            {
	            _pReaderApp.AddCommandUI({
	                UIName: "SearchPrev",
	                CommandName: 'SearchPrev',
	                State: false,
	                CreateHtmlContentFunc: function () {
	                    return "<a id='btnPrevSearch' class='fwr_toolbar_btn fwr_toolbar_search_btn fwr_toolbar_search_prev_dis' title='" + _Language.Search.FindPrev + "' style='' cmd='" + "SearchPrev" + "'></a>";
	                }, 
	                OnCommandStateChange: function (data) {
	                    FXREADER.Common.UpdateBtnState('btnPrevSearch', "fwr_toolbar_search_prev_nor", "fwr_toolbar_search_prev_dis", data.state);
	                }
	            });
	            _pReaderApp.AddCommand({
	                state: false,
	                name: "SearchPrev",
	                exec: function (data) {
	                    _SearchTextCall(FXREADER.SearchDirection.Up);
	                }
	            });
	            _pReaderApp.AddCommandUI({
	                UIName: "SearchNext",
	                CommandName: 'SearchNext',
	                State: false,
	                CreateHtmlContentFunc: function () {
	                    return "<a id='btnNextSearch' class='fwr_toolbar_btn fwr_toolbar_search_btn fwr_toolbar_search_next_dis' title='" + _Language.Search.FindNext + "' style='' cmd='" + "SearchNext" + "'></a>";
	                },
	                OnCommandStateChange: function (data) {
	                    FXREADER.Common.UpdateBtnState('btnNextSearch', "fwr_toolbar_search_next_nor", "fwr_toolbar_search_next_dis", data.state);
	                }
	            });
	            _pReaderApp.AddCommand({
	                state: false,
	                name: "SearchNext",
	                exec: function (data) {
	                    _SearchTextCall(FXREADER.SearchDirection.Down);
	                }
	            });
            }
        };
        
        //Doc View 消息响应;
        this.OnDocViewZoom = function (scale) {
            var pPageView = _pReaderApp.GetMainView().GetDocView().GetPageView(_curSearchedPageIndex);
            if (pPageView != null && _HighlightRects != null)
                _self.HighLightRects(pPageView, _HighlightRects);
        };
		
	};


	exports.Reader_CreatePlugin = function (pReaderApp) {
        var pFindToolPlugin = new FXREADER.CFindToolPlugin(pReaderApp);
        return pFindToolPlugin;
    };
});